package com.bawei.module_live.ui.liveDateil

import android.app.AlertDialog
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.alibaba.android.arouter.facade.annotation.Route
import com.bawei.module_live.R
import com.bawei.module_live.databinding.ActivityLiveDateilBinding
import com.bawei.module_live.data.LiveData
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.common.MediaItem
import android.widget.Button
import androidx.media3.common.Player
import com.bumptech.glide.Glide
import com.google.android.material.bottomsheet.BottomSheetDialog
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import com.bawei.module_live.ui.adapter.MoreLiveAdapter
import com.bawei.module_live.ui.LiveRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import com.alibaba.android.arouter.launcher.ARouter
import com.bawei.lib_common.entity.ResponseEntity
import com.bawei.module_live.ui.LiveIntent
import com.bawei.module_live.ui.LiveViewModel
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.bawei.module_live.data.LiveShopData
import com.bawei.module_live.ui.LiveState
import com.bawei.module_live.ui.adapter.LiveShopAdapter
import kotlinx.coroutines.flow.collectLatest
import com.bawei.module_live.data.OrderHotData
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.util.Log
import android.widget.ImageView
import com.bawei.module_live.TopRoundedCornersTransformation
import android.view.WindowManager
import android.view.Gravity
import android.os.CountDownTimer
import android.widget.TextView
import com.bawei.module_live.data.GiftData
import com.bawei.module_live.data.LuckData
import com.bawei.module_live.ui.adapter.GiftAdapter
import com.bawei.module_live.ui.adapter.LuckListAdapter
import com.bawei.module_live.ui.adapter.GiftCountAdapter
import com.bawei.module_live.ui.view.RedCircleCountDownView
import com.tencent.mmkv.MMKV
import master.flame.danmaku.controller.DrawHandler
import master.flame.danmaku.danmaku.model.BaseDanmaku
import master.flame.danmaku.danmaku.model.DanmakuTimer
import master.flame.danmaku.danmaku.model.android.DanmakuContext
import master.flame.danmaku.danmaku.model.android.Danmakus
import master.flame.danmaku.danmaku.parser.BaseDanmakuParser
import master.flame.danmaku.ui.widget.DanmakuView
import android.view.ViewGroup
import android.widget.Toast
import com.bawei.module_live.ui.fragment.OrderHotAllFragment
import com.bawei.module_live.ui.fragment.OrderHotDaihuoFragment

import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.bawei.module_live.ui.view.RankingPopup
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.BottomPopupView
import android.view.LayoutInflater
import android.widget.FrameLayout
import android.graphics.PixelFormat
import android.os.Handler
import com.bawei.lib_storage.mmkv.AuthMMKV
import com.bawei.lib_storage.mmkv.AuthMMKV.username
import com.bawei.module_live.data.LiveRoomData
import com.bawei.module_live.ui.adapter.ChatAdapter
import com.bawei.module_live.ui.adapter.LiveRoomAdapter
import com.hyphenate.EMMessageListener
import com.hyphenate.chat.EMClient
import com.hyphenate.chat.EMMessage
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import okhttp3.*
import okio.ByteString
import org.json.JSONObject
import com.hyphenate.exceptions.HyphenateException
import com.hyphenate.EMCallBack
import com.hyphenate.chat.EMChatRoom
import com.hyphenate.EMValueCallBack
import android.os.Looper
import androidx.lifecycle.ViewModelProvider
import com.bawei.lib_mvi.Router
import com.bawei.module_live.data.RoomIdBody
import com.bawei.module_live.data.SendGiftRequest
import com.hyphenate.chat.EMTextMessageBody
import com.opensource.svgaplayer.SVGAImageView
import com.opensource.svgaplayer.SVGAParser
import com.opensource.svgaplayer.SVGAVideoEntity
import com.opensource.svgaplayer.SVGACallback
import kotlinx.coroutines.flow.first

import com.bawei.module_live.ui.adapter.BannerAdapter
import com.bawei.module_live.ui.fragment.OnRankingItemClickListener
import com.bawei.module_live.data.Record
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import java.lang.reflect.Type
import com.bumptech.glide.load.resource.bitmap.RoundedCorners


data class User(
    val avatarUrl: String,
    val nickname: String,
    var diamond: Int
)



@Route(path = Router.Ui.LIVE_DETAIL_ACTIVITY)
class LiveDateilActivity : AppCompatActivity(), OnRankingItemClickListener {
    companion object {
        // 全局单例引用
        var instance: LiveDateilActivity? = null
        // 提供外部关闭方法
        fun finishIfExists() {
            instance?.finish()
            instance = null
        }
    }

    // ======================== 变量声明 ========================
    private lateinit var binding: ActivityLiveDateilBinding
    private var exoPlayer: ExoPlayer? = null
    private val liveRepository = LiveRepository()
    private val coroutineScope = CoroutineScope(Dispatchers.Main)
    private lateinit var liveViewModel: LiveViewModel
    private var isGoodsDialogShowing = false
    private lateinit var danmakuView: DanmakuView
    private lateinit var danmakuContext: DanmakuContext
    private val giftBubbleMap = mutableMapOf<Int, Pair<View, Int>>() // key: giftId, value: (bubbleView, count)
    private lateinit var liveRoomAdapter: LiveRoomAdapter
    private var currentRoomId: String? = null
    private lateinit var chatAdapter: ChatAdapter
    private lateinit var flagGoodsView: View // 新增
    private var currentShopList: List<Record> = emptyList() // 新增
    private lateinit var flagAdView: View // 新增广告悬浮view
    private var currentFlagGoodsId: String? = null // 新增：记录当前讲解商品id

    // 环信聊天室ID
    private val chatRoomId = "285417033236483" // 全局唯一聊天室ID
    private var isMessageListenerRegistered = false // 避免重复注册

    // 礼物、红包、弹窗等
    private var giftDialog: Dialog? = null
    private var redEnvelopeDialog: Dialog? = null
    private var moreLiveDialog: Dialog? = null
    private var bannerHandler: Handler? = null
    private var adDialog: Dialog? = null
    private var redEnvelopeCountDownTimer: CountDownTimer? = null
    private var rankingPopup: RankingPopup? = null

    // WebSocket相关
    private var webSocket: WebSocket? = null
    private var wsClient: OkHttpClient? = null
    private var wsReconnectAttempts = 0
    private val MAX_WS_RECONNECT = 5
    private var wsRoomId: String? = null
    private var wsUserId: String? = null
    private var wsConnected = false

    // 在线人数、红包轮询
    private var onlineCountJob: Job? = null
    private var redPacketStatusJob: Job? = null
    private val bigGiftIds = setOf(1, 3, 6) // 跑车、王冠、玫瑰的id

    // ======================== 生命周期 ========================
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        instance = this // 记录当前实例
        liveViewModel = ViewModelProvider(this)[LiveViewModel::class.java]
        enableEdgeToEdge()
        setContentView()
        setWindowInsets()
        initViews()
        // 适配器初始化
        liveRoomAdapter = LiveRoomAdapter()
        chatAdapter = ChatAdapter()
        binding.chatRecyclerView.adapter = chatAdapter
        binding.chatRecyclerView.layoutManager = LinearLayoutManager(this)
        // 弹幕初始化
        initDanmaku()
        // 注册环信消息监听
        registerHyphenateListener()
        // 确保环信连接
        ensureHyphenateConnection()
        // 接收数据
        receiveLiveData()
        // 监听LiveState
        observeLiveState()
        // 初始化flagGoodsView
        flagGoodsView = findViewById(R.id.flagGoods)
        flagGoodsView.visibility = View.GONE
        // 初始化flagAdView
        flagAdView = findViewById(R.id.flagAd)
        flagAdView.visibility = View.GONE
        // 广告关闭按钮
        flagAdView.findViewById<ImageView>(R.id.ad_flag_close).setOnClickListener {
            flagAdView.visibility = View.GONE
        }
    }



    override fun onPause() {
        super.onPause()
        onlineCountJob?.cancel()
        danmakuView.pause()
        // 页面不可见时暂停播放器，防止声音继续播放
        exoPlayer?.pause()
    }

    override fun onStop() {
        super.onStop()
        // 页面不可见时彻底释放播放器资源，防止切换页面后声音残留
        exoPlayer?.release()
        exoPlayer = null
    }

    override fun onResume() {
        super.onResume()
        if (onlineCountJob?.isActive != true && currentRoomId != null) {
            startOnlineCountPolling(currentRoomId!!)
        }
        danmakuView.resume()
    }

    override fun onDestroy() {
        super.onDestroy()
        if (instance == this) instance = null // 页面销毁时清理引用
        // 资源释放
        redPacketStatusJob?.cancel()
        redEnvelopeCountDownTimer?.cancel()
        currentRoomId?.let { roomId ->
            lifecycleScope.launch {
                try {
                    withContext(Dispatchers.IO) {
                        liveRepository.exitLiveRoom(roomId).collect { }
                    }
                } catch (_: Exception) {}
            }
        }
        // 页面销毁时彻底释放播放器资源，防止声音残留
        exoPlayer?.release()
        exoPlayer = null
        danmakuView.release()
        webSocket?.close(1000, "Activity destroyed")
        wsClient?.dispatcher?.executorService?.shutdown()
        if (isMessageListenerRegistered) {
            EMClient.getInstance().chatManager().removeMessageListener(messageListener)
            isMessageListenerRegistered = false
            Log.d("环信调试", "removeMessageListener: 已移除监听器")
        }
        giftDialog?.dismiss(); redEnvelopeDialog?.dismiss(); moreLiveDialog?.dismiss(); adDialog?.dismiss();
        bannerHandler?.removeCallbacksAndMessages(null)
        liveRoomAdapter.setOnEnterLiveRoomListener { _, _ -> }
        if (isMessageListenerRegistered) {
            EMClient.getInstance().chatManager().removeMessageListener(messageListener)
            isMessageListenerRegistered = false
        }
        // 关闭WebSocket等资源
        webSocket?.close(1000, "Activity destroyed")
        webSocket = null

    }

    // ======================== UI与弹幕初始化 ========================
    private fun setContentView() {
        binding = ActivityLiveDateilBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }
    private fun setWindowInsets() {
        ViewCompat.setOnApplyWindowInsetsListener(binding.parentView) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }
    }
    private fun initViews() {
        // 其他UI初始化
    }
    private fun initDanmaku() {
        danmakuView = findViewById(R.id.danmaku_view)
        danmakuContext = DanmakuContext.create()
        danmakuView.enableDanmakuDrawingCache(true)
        danmakuView.setCallback(object : DrawHandler.Callback {
            override fun prepared() { danmakuView.start() }
            override fun updateTimer(timer: DanmakuTimer?) {}
            override fun drawingFinished() {}
            override fun danmakuShown(danmaku: BaseDanmaku?) {}
        })
        danmakuView.prepare(object : BaseDanmakuParser() {
            override fun parse(): Danmakus = Danmakus()
        }, danmakuContext)
    }

    // ======================== 环信消息链路 ========================
    /**
     * 环信消息监听器，收到消息插入聊天区和处理礼物
     */
    private val messageListener = object : EMMessageListener {
        override fun onMessageReceived(messages: List<EMMessage>?) {
            Log.d("环信调试", "onMessageReceived: 收到消息, size=${messages?.size}")
            messages?.forEach { msg ->
                Log.d("环信调试", "onMessageReceived: 消息内容: ${msg.body}, from: ${msg.from}, to: ${msg.to}, attributes: ${msg.attributes}")
                // 聊天区插入
                runOnUiThread {
                    chatAdapter.addMessage(msg)
                    binding.chatRecyclerView.scrollToPosition(chatAdapter.itemCount - 1)
                }
            }
        }
        override fun onCmdMessageReceived(messages: List<EMMessage>?) {}
        override fun onMessageRead(messages: List<EMMessage>?) {}
        override fun onMessageDelivered(messages: List<EMMessage>?) {}
        override fun onMessageRecalled(messages: List<EMMessage>?) {}
        override fun onMessageChanged(message: EMMessage?, change: Any?) {}
    }
    /**
     * 注册环信消息监听
     */
    private fun registerHyphenateListener() {
        if (!isMessageListenerRegistered) {
            EMClient.getInstance().chatManager().addMessageListener(messageListener)
            isMessageListenerRegistered = true
        }
    }
    /**
     * 确保环信连接状态，未登录则登录，已登录则join
     */
    private fun ensureHyphenateConnection() {
        Log.d("环信调试", "ensureHyphenateConnection: 开始检查环信连接状态, 当前账号: $username")
        if (!EMClient.getInstance().isLoggedInBefore) {
            Log.d("环信调试", "ensureHyphenateConnection: 环信未登录，开始登录 username=$username")
            EMClient.getInstance().login(username, "123456", object : EMCallBack {
                override fun onSuccess() {
                    Log.d("环信调试", "环信登录成功 username=$username")
                    runOnUiThread { joinGroupIfNeeded() }
                }
                override fun onError(code: Int, error: String?) {
                    Log.e("环信调试", "环信登录失败: code=$code, error=$error, username=$username")
                    runOnUiThread { showToast("环信登录失败: $error") }
                }
                override fun onProgress(progress: Int, status: String?) {
                    Log.d("环信调试", "环信登录进度: $progress, $status, username=$username")
                }
            })
        } else {
            Log.d("环信调试", "环信已登录，直接加入群聊 username=$username")
            joinGroupIfNeeded()
        }
    }
    /**
     * 只在未加入群聊时调用 joinGroup
     */
    fun joinGroupIfNeeded() {
        val groupId = chatRoomId
        val group = EMClient.getInstance().groupManager().getGroup(groupId)
        Log.d("环信调试", "joinGroupIfNeeded: 检查是否已在群组, 当前账号: ${EMClient.getInstance().currentUser}")
        if (group != null && group.members.contains(EMClient.getInstance().currentUser)) {
            Log.d("环信调试", "joinGroupIfNeeded: 已经是群成员, 注册监听器")
            if (!isMessageListenerRegistered) {
                EMClient.getInstance().chatManager().addMessageListener(messageListener)
                isMessageListenerRegistered = true
                Log.d("环信调试", "addMessageListener: 注册成功")
            }
        } else {
            Log.d("环信调试", "joinGroupIfNeeded: 不是群成员, 尝试加入聊天室 chatRoomId=$chatRoomId")
            lifecycleScope.launch(Dispatchers.IO) {
                try {
                    EMClient.getInstance().chatroomManager().joinChatRoom(chatRoomId, object : EMValueCallBack<EMChatRoom> {
                        override fun onSuccess(value: EMChatRoom?) {
                            Log.d("环信调试", "joinChatRoom: 加入聊天室成功 chatRoomId=$chatRoomId, 当前账号: ${EMClient.getInstance().currentUser}")
                            runOnUiThread {
                                if (!isMessageListenerRegistered) {
                                    EMClient.getInstance().chatManager().addMessageListener(messageListener)
                                    isMessageListenerRegistered = true
                                    Log.d("环信调试", "addMessageListener: 注册成功")
                                }
                            }
                        }
                        override fun onError(error: Int, errorMsg: String?) {
                            Log.e("环信调试", "joinChatRoom: 加入聊天室失败 chatRoomId=$chatRoomId, error=$error, errorMsg=$errorMsg")
                        }
                    })
                } catch (e: HyphenateException) {
                    Log.e("环信调试", "joinChatRoom: 加入聊天室异常 chatRoomId=$chatRoomId, exception=${e.message}")
                }
            }
        }
    }
    /**
     * 发送消息（弹幕/评论）
     */
    fun sendMessage(content: String, nickname: String) {
        Log.d("环信调试", "sendMessage: 开始发送消息: content=$content, nickname=$nickname")
        val message = EMMessage.createTxtSendMessage(content, chatRoomId)
        message.chatType = EMMessage.ChatType.ChatRoom
        message.setAttribute("nickname", nickname)
        EMClient.getInstance().chatManager().sendMessage(message)
        message.setMessageStatusCallback(object : EMCallBack {
            override fun onSuccess() { Log.d("环信调试", "sendMessage: 消息发送成功") }
            override fun onError(code: Int, error: String?) { Log.e("环信调试", "sendMessage: 消息发送失败: code=$code, error=$error") }
            override fun onProgress(progress: Int, status: String?) { Log.d("环信调试", "sendMessage: 消息发送进度: $progress, $status") }
        })
        // 发送后本地插入
        chatAdapter.addMessage(message)
        binding.chatRecyclerView.scrollToPosition(chatAdapter.itemCount - 1)
        Log.d("环信调试", "sendMessage: 消息已添加到本地聊天列表")
    }

    // ======================== 红包相关 ========================
    // 检查红包状态并控制红包入口显示
    private fun checkRedPacketStatus(roomId: String) {
        lifecycleScope.launch {
            try {
                if (!roomId.isNullOrEmpty()) {
                    liveRepository.getRedPacketResult(RoomIdBody(roomId)).collect { result ->
                        val data = result.data
                        if (result.code == 200 && data != null && data.status == 1) {
                            binding.redEnvelope.visibility = View.VISIBLE
                            // 先取消上一个倒计时
                            redEnvelopeCountDownTimer?.cancel()
                            val endTime = (data.time ?: 0L) + 60_000 // 延迟1分钟
                            val now = System.currentTimeMillis()
                            val remain = endTime - now
                            if (remain > 0) {
                                redEnvelopeCountDownTimer = object : CountDownTimer(remain, 1000) {
                                    override fun onTick(millisUntilFinished: Long) {
                                        val totalSeconds = millisUntilFinished / 1000
                                        val hours = totalSeconds / 3600
                                        val minutes = (totalSeconds % 3600) / 60
                                        val seconds = totalSeconds % 60
                                        val timeStr = String.format("红包倒计时：%02d:%02d:%02d", hours, minutes, seconds)
                                        findViewById<TextView>(R.id.red_envelope_time).text = timeStr
                                    }
                                    override fun onFinish() {
                                        findViewById<TextView>(R.id.red_envelope_time).text = ""
                                    }
                                }.start()
                            } else {
                                findViewById<TextView>(R.id.red_envelope_time).text = ""
                            }
                        } else {
                            binding.redEnvelope.visibility = View.GONE
                            redEnvelopeCountDownTimer?.cancel()
                            findViewById<TextView>(R.id.red_envelope_time).text = ""
                        }
                    }
                } else {
                    binding.redEnvelope.visibility = View.GONE
                    redEnvelopeCountDownTimer?.cancel()
                    findViewById<TextView>(R.id.red_envelope_time).text = ""
                }
            } catch (e: Exception) {
                binding.redEnvelope.visibility = View.GONE
                redEnvelopeCountDownTimer?.cancel()
                findViewById<TextView>(R.id.red_envelope_time).text = ""
            }
        }
    }

    // 启动红包状态轮询
    private fun startRedPacketStatusPolling(roomId: String) {
        redPacketStatusJob?.cancel()
        redPacketStatusJob = lifecycleScope.launch {
            while (isActive) {
                checkRedPacketStatus(roomId)
                delay(5000)
            }
        }
    }

    // 启动在线人数轮询
    private fun startOnlineCountPolling(roomId: String) {
        onlineCountJob?.cancel()
        onlineCountJob = lifecycleScope.launch {
            delay(500) // 进入房间后延迟拉一次
            fetchOnlineUserCount(roomId)
            while (isActive) {
                delay(5000)
                fetchOnlineUserCount(roomId)
            }
        }
    }

    // 显示红包弹窗
    private fun showRedEnvelopeDialog() {
        val dialogView = layoutInflater.inflate(R.layout.dialog_red_envelope, null)
        val dialog = Dialog(this)
        dialog.setContentView(dialogView)
        dialog.setCancelable(true)
        dialog.setCanceledOnTouchOutside(true)
        dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
        dialog.window?.setLayout(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT
        )
        dialog.window?.setGravity(Gravity.CENTER)

        val rcd = dialogView.findViewById<RedCircleCountDownView>(R.id.rcd)
        val btnLook = dialogView.findViewById<TextView>(R.id.rob_look_fortune)
        val robPrizeLayout = dialogView.findViewById<View>(R.id.rob_prize_layout)
        val robLayout = dialogView.findViewById<View>(R.id.rob_layout)
        val listLayout = dialogView.findViewById<View>(R.id.list_layout)
        val robRv = dialogView.findViewById<RecyclerView>(R.id.rob_rv)
        val close = dialogView.findViewById<ImageView>(R.id.red_close)
        val tvTitle = dialogView.findViewById<TextView>(R.id.rob_title) // "手慢了"
        val tvDesc = dialogView.findViewById<TextView>(R.id.rob_desc)   // "送你一个好运气"

        // 关闭
        close.setOnClickListener { dialog.dismiss() }

        // 初始状态：显示5秒倒计时，隐藏"抢"按钮和"查看大家手气"
        rcd.visibility = View.VISIBLE
        rcd.setText("5")
        rcd.setProgress(1f)
        rcd.isClickable = false
        robPrizeLayout.visibility = View.GONE
        robLayout.visibility = View.VISIBLE
        listLayout.visibility = View.GONE
        btnLook.visibility = View.GONE // 初始隐藏

        // 5秒倒计时，进度和数字同步
        val totalMillis = 5000L
        object : CountDownTimer(totalMillis, 100) {
            override fun onTick(millisUntilFinished: Long) {
                val seconds = (millisUntilFinished / 1000).toInt() + 1
                rcd.setText("$seconds")
                val progress = millisUntilFinished / totalMillis.toFloat()
                rcd.setProgress(progress)
            }
            override fun onFinish() {
                rcd.setText("抢")
                rcd.setProgress(0f)
                rcd.isClickable = true
            }
        }.start()

        // 抢红包
        rcd.setOnClickListener {
            if (rcd.text == "抢") {
                rcd.visibility = View.GONE
                robPrizeLayout.visibility = View.VISIBLE
                robLayout.visibility = View.VISIBLE
                listLayout.visibility = View.GONE
                btnLook.visibility = View.VISIBLE // 抢完后才显示
                currentRoomId?.let { roomId ->
                    lifecycleScope.launch {
                        val response = liveRepository.joinRedPacket(RoomIdBody(roomId)).first()
                        if (response.code == 200 && response.data == true) {
                            // 抢到红包
                            tvTitle.text = "恭喜你抢到红包！"
                            tvDesc.text = "快去查看你的奖励吧"
                        } else {
                            // 没抢到
                            tvTitle.text = "手慢了"
                            tvDesc.text = "送你一个好运气"
                        }
                    }
                }
            }
        }

        // 查看大家手气
        btnLook.setOnClickListener {
            robLayout.visibility = View.GONE
            listLayout.visibility = View.VISIBLE
            btnLook.visibility = View.GONE
            // 拉取真实中奖数据
            currentRoomId?.let { roomId ->
                lifecycleScope.launch {
                    val response = liveRepository.getRedPacketResult(RoomIdBody(roomId)).first()
                    val data = response.data
                    Log.d("RedPacketDebug", "接口返回data.users=${data?.users}")
                    if (response.code == 200 && data != null && data.users != null) {
                        val userList: List<String> = when (val users = data.users) {
                            is String -> {
                                val str = users.trim()
                                Log.d("RedPacketDebug", "users字段为String, 内容=$str")
                                when {
                                    str.startsWith("[") -> {
                                        // JSON数组字符串
                                        try {
                                            val arr = org.json.JSONArray(str)
                                            val list = List(arr.length()) { arr.getString(it) }
                                            Log.d("RedPacketDebug", "解析JSONArray后userList=$list")
                                            list
                                        } catch (e: Exception) {
                                            Log.e("RedPacketDebug", "解析JSONArray异常: ${e.message}")
                                            emptyList()
                                        }
                                    }
                                    str.isNotEmpty() -> {
                                        Log.d("RedPacketDebug", "users为单个用户名字符串: $str")
                                        listOf(str)
                                    }
                                    else -> emptyList()
                                }
                            }
                            is List<*> -> {
                                val list = users.filterIsInstance<String>()
                                Log.d("RedPacketDebug", "users字段为List, 解析后userList=$list")
                                list
                            }
                            else -> {
                                Log.d("RedPacketDebug", "users字段为未知类型: ${users?.javaClass?.name}")
                                emptyList()
                            }
                        }
                        Log.d("RedPacketDebug", "最终userList=$userList")
                        val luckList = userList.map { name -> LuckData(name, 500) }
                        Log.d("RedPacketDebug", "luckList=$luckList, size=${luckList.size}")
                        robRv.layoutManager = LinearLayoutManager(this@LiveDateilActivity)
                        robRv.adapter = LuckListAdapter(luckList)
                        Log.d("RedPacketDebug", "LuckListAdapter已设置, itemCount=${luckList.size}")
                    } else {
                        Log.e("RedPacketDebug", "中奖名单接口返回异常: code=${response.code}, msg=${response.msg}, data=${data}")
                        showToast(response.msg ?: "暂无中奖信息")
                    }
                }
            }
        }

        redEnvelopeDialog = dialog
        dialog.show()
    }

    // 显示更多直播弹窗
    private fun showMoreLiveDialog() {
        val dialogView = layoutInflater.inflate(R.layout.dialog_more_live, null)
        val dialog = Dialog(this)
        dialog.setContentView(dialogView)
        dialog.setCancelable(true)

        // 设置弹窗宽高和位置
        val window = dialog.window
        window?.setLayout(
            (resources.displayMetrics.widthPixels * 0.8).toInt(),
            (resources.displayMetrics.heightPixels * 1.0).toInt()
        )
        window?.setGravity(Gravity.END)
        window?.setWindowAnimations(R.style.RightDialogAnimation)
        window?.setBackgroundDrawableResource(android.R.color.transparent)

        // 轮播图初始化（如有）
        val viewPager = dialogView.findViewById<ViewPager2>(R.id.bannerViewPager)
        val bannerImages = listOf(
            "https://jystest-resource.iwubida.com/smartdms/2023/11/WV8gmYJkYc5xHJvE2o-DM.png",
            "https://jystest-resource.iwubida.com/smartdms/2024/03/1VjqUrjeHnYcVdnXv4gBN.jpg",
            "https://jystest-resource.iwubida.com/smartdms/2024/08/I36u_3iQZZQsVpkZeRG8C.jpg"
        )
        viewPager.adapter = BannerAdapter(bannerImages)

        // 自动轮播
        val handler = Handler(mainLooper)
        val runnable = object : Runnable {
            override fun run() {
                val next = (viewPager.currentItem + 1) % bannerImages.size
                viewPager.currentItem = next
                handler.postDelayed(this, 3000)
            }
        }
        handler.postDelayed(runnable, 3000)
        bannerHandler = handler // 保存为成员变量
        dialog.setOnDismissListener { handler.removeCallbacks(runnable) }

        // 获取RecyclerView和相关视图
        val recyclerView = dialogView.findViewById<RecyclerView>(R.id.more_live_rv)
        val retryButton = dialogView.findViewById<Button>(R.id.retry_button)

        // 设置RecyclerView的布局管理器
        recyclerView.layoutManager = GridLayoutManager(this, 2)
        recyclerView.adapter = liveRoomAdapter

        // 点击事件：先请求加入直播间接口，成功后跳转
        liveRoomAdapter.setOnEnterLiveRoomListener { liveRoomData, position ->
            dialog.dismiss()
            onLiveRoomClicked(liveRoomData)
        }

        // 重试按钮
        retryButton.setOnClickListener {
            loadMoreLiveData(dialogView)
        }

        // 加载数据
        loadMoreLiveData(dialogView)

        moreLiveDialog = dialog
        dialog.show()
    }

    // 加载更多直播数据
    private fun loadMoreLiveData(dialogView: View) {
        val recyclerView = dialogView.findViewById<RecyclerView>(R.id.more_live_rv)
        val loadingView = dialogView.findViewById<View>(R.id.loading_view)
        val errorView = dialogView.findViewById<View>(R.id.error_view)
        val emptyView = dialogView.findViewById<View>(R.id.empty_view)

        loadingView.visibility = View.VISIBLE
        recyclerView.visibility = View.GONE
        errorView.visibility = View.GONE
        emptyView.visibility = View.GONE

        coroutineScope.launch {
            try {
                val liveRoomList = withContext(Dispatchers.IO) {
                    var result: List<LiveRoomData> = emptyList()
                    liveRepository.getLiveRoomList().collect { response ->
                        result = response.data ?: emptyList()
                    }
                    result
                }
                loadingView.visibility = View.GONE
                if (liveRoomList.isNotEmpty()) {
                    liveRoomAdapter.setData(liveRoomList)
                    recyclerView.visibility = View.VISIBLE
                } else {
                    emptyView.visibility = View.VISIBLE
                }
            } catch (e: Exception) {
                loadingView.visibility = View.GONE
                errorView.visibility = View.VISIBLE
                showToast("加载失败: ${e.message}")
            }
        }
    }

    // 直播间点击事件
    private fun onLiveRoomClicked(liveRoomData: LiveRoomData) {
        if (liveRoomData.room_id.isNullOrEmpty()) {
            showToast("房间ID无效")
            return
        }
        showLoadingDialog()
        coroutineScope.launch {
            try {
                var joinSuccess = false
                withContext(Dispatchers.IO) {
                    liveRepository.enterLiveRoom(liveRoomData.room_id!!).collect { response ->
                        joinSuccess = response.code == 200 && response.data == true
                    }
                }
                hideLoadingDialog()
                if (joinSuccess) {
                    switchRoom(liveRoomData.toLiveData())
                } else {
                    showToast("加入直播间失败")
                }
            } catch (e: Exception) {
                hideLoadingDialog()
                showToast("网络异常: ${e.message}")
            }
        }
    }

    // 显示加载弹窗
    private fun showLoadingDialog() {
        // 可自定义加载弹窗，这里用Toast占位
        showToast("加载中...")
    }

    // 隐藏加载弹窗
    private fun hideLoadingDialog() {
        // 可自定义关闭加载弹窗，这里无操作
    }

    // 切换直播间
    private fun switchRoom(newLiveData: LiveData) {
        // 释放旧播放器，防止切换房间后声音残留
        exoPlayer?.release()
        exoPlayer = null
        // 1. 关闭旧 WebSocket
        webSocket?.close(1000, "Switch room")
        wsClient?.dispatcher?.executorService?.shutdown()
        // 2. 取消红包、观众数等 Job
        redPacketStatusJob?.cancel()
        onlineCountJob?.cancel()
        // 3. 清理 UI（如弹幕、聊天、礼物等）
        chatAdapter.clearMessages()
        danmakuView.clear()
        // 4. 更新 currentRoomId
        currentRoomId = newLiveData.room_id ?: newLiveData.item_id
        Log.d("LiveDebug", "【currentRoomId赋值】currentRoomId=$currentRoomId")
        // 5. 重新连接 WebSocket
        connectWebSocket(currentRoomId!!, AuthMMKV.uId.toString())
        // 6. 重新拉取房间数据并刷新 UI
        updateUI(newLiveData)
        setupClickListeners(newLiveData)
        checkRedPacketStatus(currentRoomId!!)
        startRedPacketStatusPolling(currentRoomId!!)
        startOnlineCountPolling(currentRoomId!!)
    }

    // 显示退出确认弹窗
    private fun showExitConfirmDialog(roomId: String) {
        val dialogView = layoutInflater.inflate(R.layout.dialog_exit_confirm, null)
        val dialog = AlertDialog.Builder(this)
            .setView(dialogView)
            .setCancelable(true)
            .create()

        dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)

        dialogView.findViewById<Button>(R.id.btnCancel).setOnClickListener {
            dialog.dismiss()
        }

        dialogView.findViewById<Button>(R.id.btnExit).setOnClickListener {
            // 这里请求退出直播间接口
            requestExitLiveRoom(roomId, dialog)
        }

        dialog.show()
    }

    // 显示商品弹窗
    private fun showGoodsCartDialog(shopList: List<Record>?, is404: Boolean = false) {
        Log.d("购物车Debug", "showGoodsCartDialog: isGoodsDialogShowing=$isGoodsDialogShowing, is404=$is404, shopList.size=${shopList?.size ?: 0}")
        if (isGoodsDialogShowing) {
            Log.d("购物车Debug", "弹窗已在显示，直接return")
            return
        }
        isGoodsDialogShowing = true

        val dialogView = layoutInflater.inflate(R.layout.dialog_goods_cart, null)
        val dialog = BottomSheetDialog(this)
        dialog.setContentView(dialogView)
        dialog.setCancelable(true)
        Log.d("购物车Debug", "弹窗Dialog已创建")

        val recyclerView = dialogView.findViewById<RecyclerView>(R.id.goods_rv)
        val emptyView = dialogView.findViewById<View>(R.id.empty_view)
        //订单点击事件
        val orderIv = dialogView.findViewById<ImageView>(R.id.order_iv)
        val orderTv = dialogView.findViewById<TextView>(R.id.order_tv)
        // 购物车按钮点击事件
        val shopCardIv = dialogView.findViewById<ImageView>(R.id.shop_card_iv)
        val shopCardTv = dialogView.findViewById<TextView>(R.id.shop_card_tv)

        // 为购物车图标和文字都添加点击事件
        shopCardIv.setOnClickListener {
            Log.d("购物车Debug", "弹窗内购物车图标点击，跳转商城")
            dialog.dismiss()
            ARouter.getInstance().build(Router.Ui.SHOP_ACTIVITY).navigation()
        }

        shopCardTv.setOnClickListener {
            Log.d("购物车Debug", "弹窗内购物车文字点击，跳转商城")
            dialog.dismiss()
            ARouter.getInstance().build(Router.Ui.SHOP_ACTIVITY).navigation()
        }
        // 为订单图标和文字都添加点击事件
        orderIv.setOnClickListener {
            Log.d("购物车Debug", "弹窗内订单图标点击，跳转订单")
            dialog.dismiss()
            ARouter.getInstance().build("/module_mall/OrderListActivity").navigation()
        }

        orderTv.setOnClickListener {
            Log.d("购物车Debug", "弹窗内订单文字点击，跳转订单")
            dialog.dismiss()
            ARouter.getInstance().build("/module_mall/OrderListActivity").navigation()
        }

        if (is404 || shopList.isNullOrEmpty()) {
            Log.d("购物车Debug", "弹窗商品数量为0，显示emptyView")
            recyclerView.visibility = View.GONE
            emptyView.visibility = View.VISIBLE
        } else {
            Log.d("购物车Debug", "弹窗商品数量为${shopList.size}，显示商品列表")
            recyclerView.visibility = View.VISIBLE
            emptyView.visibility = View.GONE
            recyclerView.layoutManager = LinearLayoutManager(this)
            recyclerView.adapter = LiveShopAdapter(shopList)
            currentShopList = shopList // 新增：保存当前商品列表
        }

        dialog.setOnDismissListener {
            Log.d("购物车Debug", "弹窗关闭，isGoodsDialogShowing=false")
            isGoodsDialogShowing = false
        }
        dialog.setOnShowListener {
            Log.d("购物车Debug", "弹窗已显示 onShowListener")
        }
        dialog.show()
        Log.d("购物车Debug", "dialog.show() 已调用")
    }

    // 显示商品空弹窗
    private fun showGoodsEmptyDialog(msg: String = "还没有数据") {
        AlertDialog.Builder(this)
            .setTitle("提示")
            .setMessage(msg)
            .setPositiveButton("确定", null)
            .show()
    }

    // 显示广告弹窗
    private fun showAdvertisementDialog() {
        val dialogView = layoutInflater.inflate(R.layout.dialog_advertisement, null)
        val dialog = Dialog(this, R.style.CustomDialog)
        dialog.setContentView(dialogView)
        dialog.setCancelable(true)

        // 设置弹窗高度为屏幕的60%，宽度为全屏
        val window = dialog.window
        window?.setLayout(
            (resources.displayMetrics.widthPixels * 1.0).toInt(),
            (resources.displayMetrics.heightPixels * 0.8).toInt()
        )
        window?.setGravity(Gravity.BOTTOM) // 关键：放到底部
        window?.setBackgroundDrawableResource(android.R.color.transparent)

        val imageView = dialogView.findViewById<ImageView>(R.id.iv_advertisement)
        Glide.with(this)
            .load(R.drawable.live_iv_advertisement) // 或者网络图片url
            .transform(TopRoundedCornersTransformation(60f)) // 60f为圆角半径
            .into(imageView)

        adDialog = dialog
        dialog.show()
    }

    // 显示礼物弹窗
    private fun showGiftDialog(giftList: List<GiftData>) {
        val dialogView = layoutInflater.inflate(R.layout.dialog_gift, null)
        val dialog = Dialog(this)
        dialog.setContentView(dialogView)
        dialog.setCancelable(true)
        dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
        dialog.window?.setDimAmount(0f)
        dialog.window?.setLayout(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.WRAP_CONTENT
        )
        dialog.window?.setGravity(Gravity.BOTTOM)
        dialog.show()
        val price = if (!AuthMMKV.homeMoney.toString().isNullOrEmpty()) AuthMMKV.homeMoney else "0"
        val tvDiamond = dialogView.findViewById<TextView>(R.id.tvDiamond)
        tvDiamond.text = "余额:${price}砖石"

        // 去充值按钮跳转
        val rechargeBtn = dialogView.findViewById<TextView>(R.id.tvRecharge)
        rechargeBtn?.setOnClickListener {
            ARouter.getInstance().build(Router.Ui.GOLD_ACTIVITY).navigation()
        }

        val giftRv = dialogView.findViewById<RecyclerView>(R.id.gift_rv)
        val adapter = GiftAdapter(giftList) { gift ->
            val userDiamond = AuthMMKV.homeMoney
            if (userDiamond < gift.price) {
                Toast.makeText(this, "余额不足", Toast.LENGTH_SHORT).show()
                return@GiftAdapter
            }
            AuthMMKV.homeMoney = userDiamond - gift.price
            tvDiamond.text = "余额:${AuthMMKV.homeMoney}砖石"

            // 只请求发送礼物接口（HTTP），不再本地直接展示动画，全部等 WebSocket 回调
            val roomId = currentRoomId ?: return@GiftAdapter
            val request = SendGiftRequest(
                giftEntity = GiftData(
                    id = gift.id,
                    imgUrl = gift.imgUrl,
                    name = gift.name,
                    price = gift.price,
                    svgaPath = gift.svgaPath,
                    title = gift.title
                ),
                room_id = roomId
            )
            lifecycleScope.launch {
                Log.d("LiveDebug", "【发送礼物请求】roomId=$roomId, userId=${AuthMMKV.uId}, giftId=${gift.id}, giftName=${gift.name}")
                val response = liveRepository.sendRoomGift(request).first()
                Log.d("LiveDebug", "【发送礼物响应】roomId=$roomId, userId=${AuthMMKV.uId}, giftId=${gift.id}, code=${response.code}, data=${response.data}, msg=${response.msg}")
                if (response.code != 200 || response.data != true) {
                    showToast(response.msg ?: "发送失败")
                }
            }
        }
        giftRv.layoutManager = GridLayoutManager(this, 4)
        giftRv.adapter = adapter

        giftDialog = dialog
    }

    // 显示礼物气泡
    fun showGiftBubble(gift: GiftData, dialogView: View? = null, isBigGift: Boolean = false, senderName: String? = null) {
        Log.d("LiveDebug", "showGiftBubble: gift = $gift")
        val rootView = findViewById<ViewGroup>(android.R.id.content)
        val giftId = gift.id

        // 已存在气泡，递增数量并重置动画
        val exist = giftBubbleMap[giftId]
        if (exist != null) {
            val (bubbleView, count) = exist
            val giftCount = bubbleView.findViewById<TextView>(R.id.gift_count)
            val newCount = count + 1
            giftCount.text = "x$newCount"
            giftBubbleMap[giftId] = bubbleView to newCount

            // 高亮缩放动画
            bubbleView.animate().cancel()
            bubbleView.alpha = 1f
            bubbleView.scaleX = 1f
            bubbleView.scaleY = 1f
            bubbleView.animate()
                .scaleX(1.2f).scaleY(1.2f).setDuration(100).withEndAction {
                    bubbleView.animate().scaleX(1f).scaleY(1f).setDuration(100).start()
                }.start()

            // 延迟消失
            bubbleView.removeCallbacks(bubbleView.tag as? Runnable)
            val removeRunnable = Runnable {
                rootView.removeView(bubbleView)
                giftBubbleMap.remove(giftId)
            }
            bubbleView.tag = removeRunnable
            bubbleView.postDelayed(removeRunnable, 1500)
            return
        }

        // 新建气泡
        val bubbleView = LayoutInflater.from(this).inflate(R.layout.view_gift_bubble, rootView, false)
        val avatar = bubbleView.findViewById<ImageView>(R.id.avatar)
        val nickname = bubbleView.findViewById<TextView>(R.id.nickname)
        val tip = bubbleView.findViewById<TextView>(R.id.tip)
        val giftIcon = bubbleView.findViewById<ImageView>(R.id.gift_icon)
        val giftCount = bubbleView.findViewById<TextView>(R.id.gift_count)

        // 使用传递的发送者名称，如果没有则使用当前登录用户名
        val displayName = senderName ?: if (!username.isNullOrEmpty()) username else "游客"
        nickname.text = displayName
        val anchorName = binding.liveDetailAuthorName.text?.toString() ?: "主播"
        tip.text = "送$anchorName"
        val imgUrl = if (gift.imgUrl.startsWith("http")) gift.imgUrl else "http://10.161.9.80:7015/${gift.imgUrl}"
        Glide.with(this).load(imgUrl).into(giftIcon)
        giftCount.text = "x1"

        val params = FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.WRAP_CONTENT,
            FrameLayout.LayoutParams.WRAP_CONTENT
        )
        params.leftMargin = 16.dp2px(this) // 更靠左
        // 自适应弹窗高度，紧贴弹窗上方；无弹窗时为55%
        if (dialogView == null) {
            params.topMargin = (rootView.height * 0.50f).toInt()
        } else {
            val dialogHeight = dialogView.height
            bubbleView.measure(0, 0)
            val bubbleHeight = bubbleView.measuredHeight
            // 如果是大礼物，气泡整体往下移一段距离（如80dp），避免与大动画重叠
            val extraOffset = if (isBigGift) 60.dp2px(this) else 0
            params.topMargin = rootView.height - dialogHeight - bubbleHeight - 24.dp2px(this) + extraOffset
        }
        rootView.addView(bubbleView, params)
        giftBubbleMap[giftId] = bubbleView to 1

        // 气泡淡入动画
        bubbleView.alpha = 0f
        bubbleView.scaleX = 1.2f
        bubbleView.scaleY = 1.2f
        bubbleView.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(300).start()

        // 延迟消失
        val removeRunnable = Runnable {
            rootView.removeView(bubbleView)
            giftBubbleMap.remove(giftId)
        }
        bubbleView.tag = removeRunnable
        bubbleView.postDelayed(removeRunnable, 1500)
    }

    // 添加弹幕
    fun addDanmaku(content: String, isSelf: Boolean = true) {
        val danmaku = danmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL)
        danmaku?.apply {
            text = content
            padding = 5
            priority = 0
            isLive = true
            time = danmakuView.currentTime + 100 // 立即显示
            textSize = 48f
            textColor = if (isSelf) Color.YELLOW else Color.WHITE
            textShadowColor = Color.BLACK
        }
        danmakuView.addDanmaku(danmaku)
    }

    // 播放SVGA动画
    fun playSVGA(byteArray: ByteArray, svgaImageView: SVGAImageView) {
        val parser = SVGAParser(this)
        parser.decodeFromInputStream(byteArray.inputStream(), "gift", object : SVGAParser.ParseCompletion {
            override fun onComplete(videoItem: SVGAVideoEntity) {
                svgaImageView.setVideoItem(videoItem)
                svgaImageView.loops = 1 // 只播放一遍
                svgaImageView.visibility = View.VISIBLE
                svgaImageView.startAnimation()
                svgaImageView.callback = object : SVGACallback {
                    override fun onPause() {}
                    override fun onFinished() {
                        svgaImageView.clearAnimation()
                        svgaImageView.setVideoItem(null)
                        svgaImageView.visibility = View.GONE
                    }
                    override fun onRepeat() {}
                    override fun onStep(frame: Int, percentage: Double) {}
                }
            }
            override fun onError() {
                // 处理错误
            }
        }, true)
    }

    // 切换直播间 (用于榜单弹窗)
    fun switchRoom(newRoomId: String, userId: String) {
        Log.d("LiveDebug", "switchRoom called, newRoomId=$newRoomId, userId=$userId")
        // 1. 关闭旧连接
        webSocket?.close(1000, "Switch room")
        wsClient?.dispatcher?.executorService?.shutdown()
        // 2. 建立新连接
        connectWebSocket(newRoomId, userId)
    }


    // 获取在线用户数
    private fun fetchOnlineUserCount(roomId: String?) {
        if (roomId.isNullOrEmpty()) return
        lifecycleScope.launch {
            try {
                withContext(Dispatchers.IO) {
                    val response = liveRepository.getLiveRoomUsers(roomId).first()
                    val count = if (response.code == 200 && response.data != null) {
                        response.data.size
                    } else {
                        0
                    }
                    withContext(Dispatchers.Main) {
                        binding.audienceNum.text = "$count"
                        Log.d("LiveDebug", "【在线人数更新】roomId=$roomId, count=$count")
                    }
                }
            } catch (e: Exception) {
                Log.e("LiveDebug", "【获取在线人数失败】roomId=$roomId, error=${e.message}")
                withContext(Dispatchers.Main) {
                    binding.audienceNum.text = "0"
                }
            }
        }
    }

    // 请求退出直播间
    private fun requestExitLiveRoom(roomId: String, dialog: Dialog) {
        if (roomId.isEmpty()) {
            showToast("房间ID无效，强制退出直播间")
            dialog.dismiss()
            finish() // 直接关闭当前页面
            return
        }
        showLoadingDialog()
        lifecycleScope.launch {
            var success = false
            try {
                withContext(Dispatchers.IO) {
                    liveRepository.exitLiveRoom(roomId).collect { response ->
                        success = response.code == 200 && response.data == true
                    }
                }
            } catch (e: Exception) {
                success = false
            }
            hideLoadingDialog()
            if (success) {
                showToast("已退出直播间")
                dialog.dismiss()
                fetchOnlineUserCount(roomId) // 退出后拉一次
                finish()
            } else {
                showToast("退出直播间失败")
            }
        }
    }

    // 连接WebSocket
    private fun connectWebSocket(roomId: String, userId: String) {
        Log.d("LiveDebug", "【WS准备连接】roomId=$roomId, userId=$userId, wsClient=${wsClient.hashCode()}")
        // 先关闭旧连接
        webSocket?.close(1000, "Switch room")
        wsClient?.dispatcher?.executorService?.shutdown()
        wsClient = OkHttpClient()
        wsRoomId = roomId
        wsUserId = userId

        val wsUrl = "ws://10.161.9.80:7015/liveRoom/websocket/${roomId}/${userId}"
        val request = Request.Builder().url(wsUrl).build()
        webSocket = wsClient?.newWebSocket(request, object : WebSocketListener() {
            override fun onOpen(webSocket: WebSocket, response: Response) {
                wsConnected = true
                Log.d("LiveDebug", "【WS连接成功】roomId=$roomId, userId=$userId, ws=${webSocket.hashCode()}, response=$response")
            }
            override fun onMessage(webSocket: WebSocket, text: String) {
                Log.d("LiveDebug", "【WS收到消息】roomId=$roomId, userId=$userId, ws=${webSocket.hashCode()}, text=$text")
                Log.d("LiveDebug", "【WS原始消息】$text")
                if (text.trim().startsWith("{")) {
                    try {
                        val jsonObj = JSONObject(text)
                        val type = jsonObj.optInt("type")
                        if (type == 8) {
                            // WebSocket type=8：礼物推送消息
                            // 小动画：普通礼物，大动画：大礼物（如跑车、王冠、玫瑰）
                            // 服务器推送礼物消息，客户端根据礼物ID判断是否为大礼物
                            val dataStr = jsonObj.optString("data")
                            val dataObj = JSONObject(dataStr)
                            val giftJson = dataObj.optJSONObject("gift")
                            val username = dataObj.optString("username")
                            Log.d("LiveDebug", "【WS收到礼物推送】roomId=$roomId, userId=$userId, ws=${webSocket.hashCode()}, giftJson=$giftJson, username=$username, 当前用户=${AuthMMKV.username}")
                            runOnUiThread {
                                // 关闭弹窗：自己发的大礼物
                                if (bigGiftIds.contains(giftJson.optInt("id")) && username == AuthMMKV.username) {
                                    giftDialog?.dismiss()
                                    giftDialog = null
                                }
                                // 展示礼物动画：
                                // 1. 小动画：普通礼物
                                // 2. 大动画：大礼物（bigGiftIds集合内的礼物ID）
                                showGiftBubble(GiftData(
                                    id = giftJson.optInt("id"),
                                    imgUrl = giftJson.optString("imgUrl"),
                                    name = giftJson.optString("name"),
                                    price = giftJson.optInt("price"),
                                    svgaPath = giftJson.optString("svgaPath"),
                                    title = giftJson.optString("title")
                                ), null, bigGiftIds.contains(giftJson.optInt("id")), username)
                                if (bigGiftIds.contains(giftJson.optInt("id"))) {
                                    // 大动画：播放SVGA特效
                                    lifecycleScope.launch {
                                        val bytes = liveRepository.downloadSVGAFile(giftJson.optString("svgaPath").substringBefore('.'))
                                        if (bytes != null) {
                                            playSVGA(bytes, binding.giftSvgaView)
                                        }
                                    }
                                }
                            }
                        } else if (type == 4) {
                            // 正在讲解的商品 - WebSocket推送
                            val data = jsonObj.opt("data")
                            if (data is String) {
                                // 可能是JSON字符串，也可能是ID
                                if (data.trim().startsWith("{")) {
                                    // JSON字符串，正常解析
                                    val dataObj = JSONObject(data)
                                    val imgUrl = dataObj.optString("mainImgUrl")
                                    val name = dataObj.optString("title")
                                    val price = dataObj.optString("purchasePrice")
                                    val dealAmount = dataObj.optString("dealAmount", "0")
                                    val sales = dataObj.optString("sales", "0")
                                    val id = dataObj.optString("id") // 获取商品ID
                                    Log.d("LiveDebug", "【WS讲解商品】imgUrl=$imgUrl, name=$name, price=$price, id=$id")
                                    runOnUiThread {
                                        showFlagGoods(imgUrl, name, price, dealAmount, sales, id)
                                    }
                                } else {
                                    // 只是ID，尝试在本地商品列表查找
                                    val goodsId = data.trim()
                                    Log.d("LiveDebug", "【WS讲解商品】收到的商品ID=$goodsId, 类型=${goodsId::class.java}")
                                    Log.d("LiveDebug", "【WS讲解商品】当前商品列表长度=${currentShopList.size}")
                                    currentShopList.forEachIndexed { index, record ->
                                        Log.d("LiveDebug", "【WS讲解商品】本地商品[$index] id=${record.id}, 类型=${record.id::class.java}")
                                    }
                                    val record = currentShopList.find { it.id.toString().trim() == goodsId.trim() }
                                    if (record != null) {
                                        Log.d("LiveDebug", "[商品浮窗] showFlagGoods调用，id=${record.id}")
                                        runOnUiThread {
                                            showFlagGoods(
                                                record.mainImgUrl,
                                                record.title,
                                                record.purchasePrice.toString(),
                                                record.marketPriceFee.toString(), // 或成交额字段
                                                record.soldNum.toString(), // 或销量字段
                                                record.id.toString() // 这里要加上 id
                                            )
                                        }
                                    } else {
                                        Log.e("LiveDebug", "【WS讲解商品】收到的data只是商品ID=$goodsId，但本地未找到该商品，尝试重新加载商品列表")
                                        // 如果本地商品列表为空，重新加载
                                        if (currentShopList.isEmpty()) {
                                            preloadGoodsList(roomId)
                                        }
                                    }
                                }
                            } else if (data is JSONObject) {
                                // 直接是对象
                                val imgUrl = data.optString("mainImgUrl")
                                val name = data.optString("title")
                                val price = data.optString("purchasePrice")
                                val dealAmount = data.optString("dealAmount", "0")
                                val sales = data.optString("sales", "0")
                                val id = data.optString("id") // 获取商品ID
                                Log.d("LiveDebug", "【WS讲解商品】imgUrl=$imgUrl, name=$name, price=$price, id=$id")
                                runOnUiThread {
                                    showFlagGoods(imgUrl, name, price, dealAmount, sales, id)
                                }
                            } else {
                                Log.e("LiveDebug", "【WS讲解商品】收到的data类型不支持: $data")
                            }
                        } else if (type == 2) {
                            // WebSocket type=2：广告
                            val data = jsonObj.opt("data")
                            Log.d("LiveDebug", "【WS广告推送】data=$data")
                            // 解析广告内容并展示
                            if (data is JSONObject) {
                                val imgUrl = data.optString("url")
                                val content = data.optString("desc")
                                runOnUiThread {
                                    showFlagAd(imgUrl, content)
                                }
                            } else if (data is String && data.trim().isNotEmpty()) {
                                // 兼容data为json字符串
                                try {
                                    val dataObj = JSONObject(data)
                                    val imgUrl = dataObj.optString("url")
                                    val content = dataObj.optString("desc")
                                    runOnUiThread {
                                        showFlagAd(imgUrl, content)
                                    }
                                } catch (e: Exception) {
                                    runOnUiThread { flagAdView.visibility = View.GONE }
                                }
                            } else {
                                runOnUiThread { flagAdView.visibility = View.GONE }
                            }
                        }
                    } catch (e: Exception) {
                        Log.e("LiveDebug", "消息解析异常", e)
                    }
                } else {
                    Log.d("LiveDebug", "收到非JSON消息: $text")
                }
            }
            override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
                wsConnected = false
                Log.e("LiveDebug", "【WS连接失败】roomId=$roomId, userId=$userId, ws=${webSocket.hashCode()}, error=${t.message}, response=$response")
                if (wsReconnectAttempts < MAX_WS_RECONNECT && wsRoomId != null && wsUserId != null) {
                    wsReconnectAttempts++
                    val delayMillis = 2000L * wsReconnectAttempts
                    Handler(Looper.getMainLooper()).postDelayed({
                        connectWebSocket(wsRoomId!!, wsUserId!!)
                    }, delayMillis)
                } else {
                    Log.e("LiveDebug", "重连次数已达上限，停止重连")
                }
            }
            override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
                wsConnected = false
                Log.d("LiveDebug", "【WS连接关闭】roomId=$roomId, userId=$userId, ws=${webSocket.hashCode()}, code=$code, reason=$reason")
            }
        })
    }

    // 监听LiveState
    private fun observeLiveState() {
        lifecycleScope.launch {
            liveViewModel.liveState.collectLatest { state ->
                when (state) {
                    LiveState.Empty -> {}
                    is LiveState.LiveShopListSuccess -> {
                        showGoodsCartDialog(state.shopList)
                    }
                    is LiveState.FocuseUserSuccess -> {
                        binding.tvFocuse.text = "已关注"
                        showToast("关注成功")
                    }
                    is LiveState.UnFocuseUserSuccess -> {
                        binding.tvFocuse.text = "关注"
                        showToast("取关成功")
                    }
                    is LiveState.Error -> {
                        showGoodsEmptyDialog(state.errorMsg)
                    }
                    LiveState.Init -> {}
                    is LiveState.LiveListSuccess -> {}
                    LiveState.Loading -> {}
                    is LiveState.GiftListSuccess -> {
                        showGiftDialog(state.list)
                    }
                    is LiveState.FocuseStatus -> {
                        binding.tvFocuse.text = if (state.isFocuse) "已关注" else "关注"
                    }
                    is LiveState.OrderHotListSuccess ->{}
                    else -> {}
                }
            }
        }
    }

    // 设置点击事件
    private fun setupClickListeners(liveData: LiveData) {
        with(binding) {
            // 关注按钮点击事件
            authorLayout.setOnClickListener {
                val focuseUserid = AuthMMKV.uId // 当前用户ID
                val focusedUserid = liveData.id // 主播ID
                lifecycleScope.launch {
                    if (binding.tvFocuse.text == "已关注") {
                        liveViewModel.intents.send(
                            LiveIntent.UnFocuseUserIntent(focuseUserid, focusedUserid)
                        )
        } else {
                        liveViewModel.intents.send(
                            LiveIntent.FocuseUserIntent(focuseUserid, focusedUserid)
                        )
                    }
                }
            }

            // 更多直播点击事件
            moreLive.setOnClickListener {
                showMoreLiveDialog()
            }

            // 关闭按钮点击事件
            liveDetailClose.setOnClickListener {
                showExitConfirmDialog(liveData.item_id)
            }

            // 礼物按钮点击事件
            gift.setOnClickListener {
                lifecycleScope.launch {
                    liveViewModel.intents.send(LiveIntent.FetchGiftListIntent)
                }
            }

            // 点赞按钮点击事件（点赞动画）
            liveDetailFav.setOnClickListener {
                klv.addLikeImages(
                    R.drawable.fav_0,
                    R.drawable.fav_1,
                    R.drawable.fav_2,
                    R.drawable.fav_3,
                    R.drawable.fav_4,
                    R.drawable.fav_5,
                )
                klv.addFavor()

            }

            // 购物车按钮点击事件
            openGoods.setOnClickListener {
                Log.d("购物车Debug", "点击了购物车按钮")
                val roomId = currentRoomId
                if (roomId.isNullOrEmpty()) {
                    Log.d("购物车Debug", "房间ID无效，无法获取商品")
                    showToast("房间ID无效，无法获取商品")
                    return@setOnClickListener
                }
                fetchGoodsAndShowDialog(roomId)
            }

            // 发送弹幕按钮点击事件
            binding.sendBarrage.setOnClickListener {
                val comment = binding.commentContent.text.toString()
                if (comment.isNotEmpty()) {
                    addDanmaku(comment, isSelf = true)
                    // 获取当前用户等级和昵称
                    val userNickname = username ?: "游客"
                    sendMessage(comment, userNickname)
                    binding.commentContent.text.clear()
                } else {
                    showToast("请输入弹幕内容")
                }
            }

            // 红包按钮点击事件
            redEnvelope.setOnClickListener {
                showRedEnvelopeDialog()
            }

            // 小时榜按钮点击事件
            hourList.setOnClickListener {
                rankingPopup = RankingPopup(this@LiveDateilActivity, this@LiveDateilActivity, defaultTab = 0)
                XPopup.Builder(this@LiveDateilActivity)
                    .dismissOnTouchOutside(true)
                    .asCustom(rankingPopup!!)
                    .show()
            }

            // 广告按钮点击事件
            liveDetailAdvertisement.setOnClickListener {
                showAdvertisementDialog()
            }

        }
    }

    // 更新UI
    private fun updateUI(liveData: LiveData) {
        with(binding) {
            liveDetailAuthorName.text = liveData.name
            Glide.with(this@LiveDateilActivity)
                .load(liveData.videomainimag)
                .circleCrop()
                .into(liveDetailAuthorIcon)
            liveDetailAuthorLikeNum.text = "${liveData.playnum}本场点赞"
            fetchOnlineUserCount(currentRoomId)
            if (liveData.videopath.isNotEmpty()) {
                // 先释放旧的播放器，防止多实例导致切换直播间后声音残留
                exoPlayer?.release()
                exoPlayer = null
                // 创建新播放器
                exoPlayer = ExoPlayer.Builder(this@LiveDateilActivity).build().apply {
                    setMediaItem(MediaItem.fromUri(liveData.videopath))
                    repeatMode = Player.REPEAT_MODE_ONE
                    prepare()
                    playWhenReady = true
                }
                playerView.player = exoPlayer
            }
            setupClickListeners(liveData)
        }
        lifecycleScope.launch {
            liveViewModel.intents.send(
                LiveIntent.CheckFocuseStatusIntent(AuthMMKV.uId, liveData.id)
            )
        }
    }

    // 接收数据
    private fun receiveLiveData() {
        // 优先 LiveRoomData
        val liveRoomData = intent.getSerializableExtra("live_data") as? LiveRoomData
        if (liveRoomData != null && !liveRoomData.room_id.isNullOrEmpty()) {
            currentRoomId = liveRoomData.room_id
            Log.d("LiveDebug", "[进入房间]currentRoomId=$currentRoomId, userId=${AuthMMKV.uId}")
            connectWebSocket(currentRoomId!!, AuthMMKV.uId.toString())
            checkRedPacketStatus(currentRoomId!!)
            startRedPacketStatusPolling(currentRoomId!!)
            // 优先加载商品列表
            preloadGoodsList(currentRoomId!!)
            val converted = liveRoomData.toLiveData()
            updateUI(converted)
            setupClickListeners(converted)
            return
        }
        // 其次 LiveData
        val liveData = intent.getSerializableExtra("live_data") as? LiveData
        if (liveData != null) {
            // 优先用room_id，再用item_id
            currentRoomId = liveData.room_id ?: liveData.item_id
            Log.d("LiveDebug", "[进入房间]currentRoomId=$currentRoomId, intentRoomId=${liveRoomData?.room_id }, userId=${AuthMMKV.uId}")
            connectWebSocket(currentRoomId!!, AuthMMKV.uId.toString())
            checkRedPacketStatus(currentRoomId!!)
            startRedPacketStatusPolling(currentRoomId!!)
            startOnlineCountPolling(currentRoomId!!)
            // 优先加载商品列表
            preloadGoodsList(currentRoomId!!)
            updateUI(liveData)
            setupClickListeners(liveData)
            return
        }
        showToast("获取直播间数据失败")
        finish()
    }

    fun showToast(msg: String) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
        } else {
            runOnUiThread {
                Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
            }
        }
    }

    override fun onRankingItemClicked(item: OrderHotData) {
        // 1. 关闭榜单弹窗
        rankingPopup?.dismiss()
        rankingPopup = null

        // 2. 切换直播间
        val liveRoomData = LiveRoomData(
            room_id = item.room_id ?: "",
            id = item.id ?: 0,
            room_name = item.room_name ?: "",
            room_description = item.room_description ?: "",
            play_url = item.play_url ?: "",
            push_url = item.push_url ?: "",
            create_time = item.create_time ?: "",
            status = item.status ?: 0,
            host_id = item.host_id ?: "",
            hot = item.hot ?: 0,
            follow = false
        )
        onLiveRoomClicked(liveRoomData)
    }

    // 预加载商品列表（不显示弹窗）
    private fun preloadGoodsList(roomId: String, onLoaded: (() -> Unit)? = null) {
        Log.d("LiveDebug", "【预加载商品】roomId=$roomId")
        lifecycleScope.launch {
            try {
                val response = liveRepository.getLiveRoomGoods(roomId).first()
                val shopData = response.data
                val shopList = shopData?.records ?: emptyList()
                Log.d("LiveDebug", "【预加载商品响应】code=${response.code}, records.size=${shopList.size}, msg=${response.msg}")
                if (response.code == 200 && shopList.isNotEmpty()) {
                    currentShopList = shopList
                    Log.d("LiveDebug", "【预加载商品成功】currentShopList.size=${currentShopList.size}")
                } else {
                    Log.w("LiveDebug", "【预加载商品失败】code=${response.code}, msg=${response.msg}")
                }
            } catch (e: Exception) {
                Log.e("LiveDebug", "【预加载商品异常】${e.message}")
            }
            onLoaded?.invoke()
        }
    }

    // 拉取商品数据并弹窗
    private fun fetchGoodsAndShowDialog(roomId: String) {
        Log.d("购物车Debug", "fetchGoodsAndShowDialog: 拉取商品 roomId=$roomId")
        lifecycleScope.launch {
            try {
                val response = liveRepository.getLiveRoomGoods(roomId).first()
                val shopData = response.data
                val shopList = shopData?.records ?: emptyList()
                Log.d("购物车Debug", "商品接口响应 code=${response.code}, records.size=${shopList.size}, msg=${response.msg}")
                if (response.code == 404 || shopList.isEmpty()) {
                    showGoodsCartDialog(shopList = null, is404 = response.code == 404)
                } else {
                    showGoodsCartDialog(shopList = shopList, is404 = false)
                }
            } catch (e: Exception) {
                Log.e("购物车Debug", "商品接口异常: ${e.message}")
                showGoodsCartDialog(shopList = null, is404 = false)
            }
        }
    }

    // 展示右下角讲解商品
    private fun showFlagGoods(imgUrl: String, name: String, price: String, dealAmount: String, sales: String, id: String? = null) {
        flagGoodsView.visibility = View.VISIBLE
        val iv = flagGoodsView.findViewById<ImageView>(R.id.ivGoodsImg)
        val tvName = flagGoodsView.findViewById<TextView>(R.id.tvGoodsTitle)
        val tvPrice = flagGoodsView.findViewById<TextView>(R.id.tvPrice)
        val tvDealAmount = flagGoodsView.findViewById<TextView>(R.id.tvDealAmount)
        val tvSales = flagGoodsView.findViewById<TextView>(R.id.tvSales)
        val btnCancel = flagGoodsView.findViewById<TextView>(R.id.btnCancel)
        val flagClose = flagGoodsView.findViewById<ImageView>(R.id.flag_close)
        Glide.with(this).load(imgUrl).into(iv)
        tvName.text = name
        tvPrice.text = "¥$price"
        tvDealAmount.text = "成交额 $dealAmount"
        tvSales.text = "销量 $sales"
        currentFlagGoodsId = id // 记录id
        val closeAction = View.OnClickListener {
            flagGoodsView.visibility = View.GONE
        }
        btnCancel.setOnClickListener(closeAction)
        flagClose.setOnClickListener(closeAction)
        // 点击跳转商品详情
        flagGoodsView.setOnClickListener {
            Log.d("LiveDebug", "[商品浮窗] 点击事件触发，currentFlagGoodsId=$currentFlagGoodsId")
            currentFlagGoodsId?.let { goodsId ->
                val intId = goodsId.toIntOrNull()
                Log.d("LiveDebug", "[商品浮窗] 转换id: goodsId=$goodsId, intId=$intId")
                if (intId != null) {
                    Log.d("LiveDebug", "[商品浮窗] 跳转ARouter，shopId=$intId")
                    ARouter.getInstance().build( Router.Ui.SHOP_DETAIL_ACTIVITY)
                        .withInt("shopId", intId)
                        .navigation()
                } else {
                    Log.e("LiveDebug", "[商品浮窗] 商品id无法转换为Int: $goodsId")
                }
            } ?: Log.e("LiveDebug", "[商品浮窗] currentFlagGoodsId为null")
        }
    }

    // 展示右下角广告
    private fun showFlagAd(imgUrl: String, content: String) {
        flagAdView.visibility = View.VISIBLE
        val iv = flagAdView.findViewById<ImageView>(R.id.ivAdImg)
        val tvContent = flagAdView.findViewById<TextView>(R.id.tvAdContent)
        Glide.with(this)
            .load(imgUrl)
            .transform(RoundedCorners(24))
            .into(iv)
        tvContent.text = content
    }




}

// FragmentAdapter 实现
class FragmentAdapter(activity: FragmentActivity, private val fragments: List<Fragment>) : FragmentStateAdapter(activity) {
    override fun getItemCount() = fragments.size
    override fun createFragment(position: Int) = fragments[position]
}

class RankingPopup(
    context: Context,
    private val activity: FragmentActivity,
    private val defaultTab: Int = 0
) : BottomPopupView(context) {

    override fun getImplLayoutId(): Int = R.layout.ranking_layout

    override fun onCreate() {
        super.onCreate()
        val tabList = listOf("全站", "带货榜")
        val vp2 = findViewById<ViewPager2>(R.id.viewPager)
        val tl = findViewById<TabLayout>(R.id.tabLayout)
        val fragments = listOf(OrderHotAllFragment(), OrderHotDaihuoFragment())
        vp2.adapter = FragmentAdapter(activity, fragments)
        TabLayoutMediator(tl, vp2) { tab, position -> tab.text = tabList[position] }.attach()
        vp2.setCurrentItem(defaultTab, false)
    }
}

fun Int.dp2px(context: Context): Int =
    (this * context.resources.displayMetrics.density + 0.5f).toInt()

